package com.weaver.qfengx.sdk.moxueyuan;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.weaver.qfengx.RequestUtils;
import com.weaver.qfengx.StringUtils;
import com.weaver.qfengx.sdk.moxueyuan.config.MxyConfig;
import com.weaver.qfengx.sdk.moxueyuan.entity.MxyResult;
import com.weaver.qfengx.sdk.moxueyuan.entity.MxyUserEntity;
import com.weaver.qfengx.sdk.moxueyuan.utils.MoxueyuanEncryptor;
import com.weaver.qfengx.sdk.welink.param.TokenParam;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Response;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * 魔学院相关操作SDK
 */
public class MxySdk {

    private String corpId;
    private String corpSecret;

    private MxyConfig mxyConfig;

    private OkHttpClient client;

    private Cache<String, String> cache = CacheBuilder.newBuilder()
            .maximumSize(1)
            .expireAfterWrite(6900, TimeUnit.SECONDS)
            .build();

    public MxySdk(String corpId, String corpSecret) {
        this(corpId, corpSecret, new MxyConfig(), new OkHttpClient());
    }

    public MxySdk(String corpId, String corpSecret, OkHttpClient client) {
        this(corpId, corpSecret, new MxyConfig(), client);
    }

    public MxySdk(String corpId, String corpSecret, MxyConfig mxyConfig) {
        this(corpId, corpSecret, mxyConfig, new OkHttpClient());
    }


    public MxySdk(String corpId, String corpSecret, MxyConfig mxyConfig, OkHttpClient client) {
        this(corpId, corpSecret, true, mxyConfig, client);
    }

    public MxySdk(String corpId, String corpSecret, boolean isLazy, MxyConfig mxyConfig, OkHttpClient client) {
        this.corpId = corpId;
        this.corpSecret = corpSecret;
        this.mxyConfig = mxyConfig;
        this.client = client;
        if (!isLazy) {
            try {
                accessToken();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("MxySdk 构建失败： " + e.getMessage());
            }
        }
    }

    public void setAccessToken(String token) {
        this.cache.put("token", token);
    }

    public Response requestAccessToken() throws IOException {
        Map<String, String> params = Maps.newHashMap();
        params.put("corpid", corpId);
        params.put("corpsecret", corpSecret);
        return RequestUtils.doGetWithoutChange(this.client,this.mxyConfig.getAccessTokenUrl(), params);
    }

    private Map<String, Object> getTokenMap() throws IOException {
        Response tokenRes = requestAccessToken();
        if (tokenRes.isSuccessful()) {
            JSONObject res = JSON.parseObject(tokenRes.body().string());
            if (StringUtils.equals(res.getString("errcode"), "0")) {
                JSONObject results = res.getJSONObject("results");
                String token = results.getString("access_token");
                long expiresTime = results.getLong("expires_in");
                Map<String, Object> resMap = Maps.newHashMap();
                resMap.put("token", token);
                resMap.put("time", expiresTime);
                return resMap;
            } else {
                throw new RuntimeException("获取token请求失败：" + res.getString("errmsg"));
            }
        } else {
            throw new RuntimeException("获取token请求异常: " + tokenRes.body().string());

        }
    }

    /**
     * 获取当前的access_token
     * @return
     */
    public String accessToken() throws ExecutionException, IOException {
        if (Objects.isNull(cache)) { // 如果是第一次，则构建缓存
            Map<String, Object> resMap = getTokenMap();
            this.cache = CacheBuilder.newBuilder()
                    .maximumSize(1)
                    .expireAfterWrite(Long.parseLong(Objects.requireNonNull(StringUtils.val(resMap.get("time")))) - 300, TimeUnit.MINUTES)
                    .build();
            this.cache.put("token", Objects.requireNonNull(StringUtils.val(resMap.get("token"))));
        }
        return cache.get("token", () -> StringUtils.val(getTokenMap().get("token")));
    }

    /**
     * 获取所有成员userid
     * @param importType 0为后台添加，空表示所有
     * @param onlyOpenUserid 是否仅查询开启成员 Y/N
     * @return
     */
    public MxyResult getUserIds(String importType, String onlyOpenUserid) throws IOException, ExecutionException {
        Map<String, String> params = Maps.newHashMap();
        params.put("import", importType);
        params.put("onlyOpenUserid", onlyOpenUserid);
        params.put("access_token", accessToken());
        Response response = RequestUtils.doGet(client, mxyConfig.getUseridsUrl(), Maps.newHashMap(), params);
        if (response.isSuccessful()) {
            return JSON.parseObject(response.body().string(), MxyResult.class);
        } else {
            throw new RuntimeException("请求异常: " + response.body().string());

        }
    }

    /**
     * 获取部门列表
     * @param id 部门ID, 空则获取所有
     * @param importType 0表示后台添加，空则表示所有
     * @return
     */
    public MxyResult getDeptList(String id, String importType) throws IOException, ExecutionException {
        Map<String, String> params = Maps.newHashMap();
        params.put("import", importType);
        params.put("id", id);
        params.put("access_token", accessToken());
        Response response = RequestUtils.doGet(client, mxyConfig.getDeptListUser(), Maps.newHashMap(), params);
        if (response.isSuccessful()) {
            return JSON.parseObject(response.body().string(), MxyResult.class);
        } else {
            throw new RuntimeException("请求异常: " + response.body().string());

        }
    }

    public MxyResult getDeptIds() throws IOException, ExecutionException {
        Map<String, String> params = Maps.newHashMap();
        params.put("access_token", accessToken());
        Response response = RequestUtils.doGet(client, mxyConfig.getDeptIds(), Maps.newHashMap(), params);
        if (response.isSuccessful()) {
            return JSON.parseObject(response.body().string(), MxyResult.class);
        } else {
            throw new RuntimeException("请求异常: " + response.body().string());

        }
    }

    /**
     * 创建用户
     * @param user
     * @return
     * @throws IOException
     */
    public MxyResult addUser(MxyUserEntity user) throws IOException, ExecutionException {
        Response response = RequestUtils.doPostByJson(client, mxyConfig.getAddUserUrl() + "?access_token=" + accessToken(), JSON.toJSONString(user));
        if (response.isSuccessful()) {
            MxyResult mxyResult = JSON.parseObject(response.body().string(), MxyResult.class);
            return mxyResult;
        } else {
            throw new RuntimeException("请求异常: " + response.body().string());

        }
    }

    public String getSsoLoginUrl(String userid, String token) throws IOException {

        Map<String, String> map = Maps.newHashMap();
        map.put("userid", userid);
        String text = JSON.toJSONString(map);
        MoxueyuanEncryptor moxueyuanEncryptor = new MoxueyuanEncryptor(token, "a64wQreq33U2ivwVporINQBEddr5aIPmItuh5XQEsSa", corpId);
        Map<String, String> jsonMap = moxueyuanEncryptor.getEncryptedMap(text);
        System.out.println(JSON.toJSONString(jsonMap));
        Map<String, String> params = Maps.newHashMap();
        params.put("scope", "base");
        params.put("corpid", corpId);
        params.put("timestamp", jsonMap.get("timeStamp"));
        params.put("nonce", jsonMap.get("nonce"));
        params.put("sign", jsonMap.get("msg_signature"));
        params.put("ticket", URLEncoder.encode(jsonMap.get("encrypt"), "utf-8"));
        params.put("redirect_uri",  URLEncoder.encode("http://pc.mxy.chinamobo.com", "utf-8"));

        HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(mxyConfig.getSsoLoginUrl()))
                .newBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            urlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
        }
        return urlBuilder.build().url().toString();
//        if (response.isSuccessful()) {
//            MxyResult mxyResult = JSON.parseObject(response.body().string(), MxyResult.class);
//            return mxyResult;
//        } else {
//            throw new RuntimeException("请求异常: " + response.body().string());
//
//        }
    }

    public static void main(String[] args) throws IOException, ExecutionException {
        MxySdk mxySdk = new MxySdk("mxyd3v1j4jh1ecm7i8s", "13UG0AK4rCsxM2MDbN7mLZrNUnXQMdjddiupJvIo0DktO2hjdIcXjzOrMAdbEUZj", new MxyConfig() {
            @Override
            public String getHostUrl() {
                return "http://open.test.moxueyuan.com";
            }
        });
        mxySdk.setAccessToken("8e4029692262672eaf810c0462fda79d68f355b1");
        System.out.println(mxySdk.accessToken());
        MxyResult res = mxySdk.getUserIds("", "Y");
        System.out.println(res.getResults());
        MxyResult deptRes = mxySdk.getDeptList("", "");
        System.out.println(deptRes.getResults());
        System.out.println(mxySdk.getDeptIds().getResults());
//        MxyUserEntity user = new MxyUserEntity()
//                .setUserid("1")
//                .setDepartment(Lists.newArrayList("0"))
//                .setName("cs01");
//        System.out.println(mxySdk.addUser(user).getResults());
        System.out.println(mxySdk.getSsoLoginUrl("1", "DGZJZeOZpK"));
    }

}































